home *** CD-ROM | disk | FTP | other *** search
- #include "PICTSprite.h"
- #include <QDOffscreen.h>
- #include <assert.h>
- #include <stdlib.h>
- #include "Q3ADUtilities.h"
-
-
-
-
- #if 0
- #pragma mark PRIVATE STRUCTURES
- #endif
-
- typedef struct iPICTOffscreen
- {
- long referenceCount;
- long basePictureID;
- long numFaces;
- GWorldPtr sourcePort;
- Rect sourceRect;
-
- struct iPICTOffscreen *nextOffscreen;
-
- } iPICTOffscreen;
-
-
- typedef struct iTPICTSprite
- {
- long currentFace;
- long totalFaces;
- iPICTOffscreen *sourceOffscreen;
- CGrafPtr destPort;
- Rect destRect;
-
- } iTPICTSprite;
-
-
- #if 0
- #pragma mark GLOBALS
- #endif
-
- iPICTOffscreen *gOffscreenHead = NULL;
-
-
- #if 0
- #pragma mark PRIVATE FUNCTION DECLARATIONS
- #endif
-
- /*
- ** PRIVATE FUNCTIONS
- */
- static TQ3Status iPICTSprite_ZeroOut(
- iTPICTSprite *inSprite);
-
-
- static TQ3Status iPICTOffscreen_ZeroOut(
- iPICTOffscreen *inPICTOffscreen);
-
- static iPICTOffscreen *iPICTOffscreen_New(
- long inNumFaces,
- long inBasePictureID);
-
- static TQ3Status iPICTOffscreen_Draw(
- iPICTOffscreen *inPICTOffscreen,
- long face,
- CGrafPtr destPort,
- const Rect *destRect
- );
-
- static TQ3Status iPICTOffscreen_Dispose(
- iPICTOffscreen *ioPICTOffscreen);
-
- static iPICTOffscreen *iPICTOffscreen_Find(
- long inBasePictureID);
-
-
-
- #if 0
- #pragma mark -
- #endif
-
- /******************************************************************************
- ** **
- ** PUBLIC FUNCTION DEFINITIONS **
- ** **
- *****************************************************************************/
-
- /*===========================================================================*\
- *
- * Routine: PICTSprite_New()
- *
- * Comments:
- *
- \*===========================================================================*/
-
- TPICTSprite *PICTSprite_New(
- long inBasePictureID,
- long inTotalFaces,
- long inStartFace,
- CGrafPtr inDestPort,
- Rect *inDestRect)
- {
- iTPICTSprite *outPICTSprite = NULL;
- PicHandle currentPicture = NULL;
-
- TQ3Status status = kQ3Success;
-
- assert(inDestPort);
-
- mBailIfNULL_(outPICTSprite = malloc(sizeof(iTPICTSprite)));
-
- iPICTSprite_ZeroOut(outPICTSprite);
-
- outPICTSprite->totalFaces = inTotalFaces;
- outPICTSprite->currentFace = inStartFace;
- outPICTSprite->destPort = inDestPort;
- outPICTSprite->destRect = *inDestRect;
-
- mBailIfNULL_(outPICTSprite->sourceOffscreen =
- iPICTOffscreen_New(inTotalFaces,inBasePictureID));
-
- return outPICTSprite;
-
- bail:
- if (outPICTSprite)
- PICTSprite_Dispose(outPICTSprite);
-
- return NULL;
- }
-
-
- /*===========================================================================*\
- *
- * Routine: PICTSprite_Dispose()
- *
- * Comments:
- *
- \*===========================================================================*/
-
- TQ3Status PICTSprite_Dispose(
- TPICTSprite *ioSprite)
- {
- assert(ioSprite);
-
- if (ioSprite->sourceOffscreen)
- iPICTOffscreen_Dispose(ioSprite->sourceOffscreen);
-
- free(ioSprite);
-
- return kQ3Success;
- }
-
-
- /*===========================================================================*\
- *
- * Routine: PICTSprite_Draw()
- *
- * Comments:
- *
- \*===========================================================================*/
-
- TQ3Status PICTSprite_Draw(
- TPICTSprite *inSprite)
- {
- TQ3Status status = kQ3Success;
-
- inSprite->currentFace =
- (inSprite->currentFace + 1) % inSprite->totalFaces;
-
- status = iPICTOffscreen_Draw(
- inSprite->sourceOffscreen,
- inSprite->currentFace,
- inSprite->destPort,
- &inSprite->destRect);
-
- return status;
- }
-
-
-
- #if 0
- #pragma mark -
- #endif
-
- /******************************************************************************
- ** **
- ** PRIVATE FUNCTION DEFINITIONS **
- ** **
- *****************************************************************************/
-
- /*===========================================================================*\
- *
- * Routine: iPICTSprite_ZeroOut()
- *
- * Comments:
- *
- \*===========================================================================*/
-
- static TQ3Status iPICTSprite_ZeroOut(
- iTPICTSprite *inSprite)
- {
- assert(inSprite);
-
- inSprite->currentFace = 0;
- inSprite->totalFaces = 0;
- inSprite->sourceOffscreen = NULL;
-
- inSprite->destPort = NULL;
-
- inSprite->destRect.top =
- inSprite->destRect.bottom =
- inSprite->destRect.left =
- inSprite->destRect.right = 0;
-
- return kQ3Success;
- }
-
-
- /*===========================================================================*\
- *
- * Routine: iPICTOffscreen_ZeroOut()
- *
- * Comments:
- *
- \*===========================================================================*/
-
- static TQ3Status iPICTOffscreen_ZeroOut(
- iPICTOffscreen *inPICTOffscreen)
- {
- assert(inPICTOffscreen);
-
- inPICTOffscreen->referenceCount = 0;
- inPICTOffscreen->basePictureID = 0;
- inPICTOffscreen->numFaces = 0;
- inPICTOffscreen->sourcePort = NULL;
-
- inPICTOffscreen->sourceRect.top =
- inPICTOffscreen->sourceRect.bottom =
- inPICTOffscreen->sourceRect.left =
- inPICTOffscreen->sourceRect.right = 0;
-
- inPICTOffscreen->nextOffscreen = NULL;
-
- return kQ3Success;
- }
-
- /*===========================================================================*\
- *
- * Routine: iPICTOffscreen_New()
- *
- * Comments:
- *
- \*===========================================================================*/
-
- static iPICTOffscreen *iPICTOffscreen_New(
- long inNumFaces,
- long inBasePictureID)
- {
-
- iPICTOffscreen *outPICTOffscreen = NULL;
- PicHandle currentPicture = NULL;
- Rect gworldRect;
-
- TQ3Status status = kQ3Success;
-
-
- /*
- ** Check to see if we've already loaded these pictures before (we use
- ** the base ID as our check).
- */
-
- outPICTOffscreen = iPICTOffscreen_Find(inBasePictureID);
-
- /*
- ** If we find one, we return it.
- */
-
- if (outPICTOffscreen)
- return outPICTOffscreen;
-
- /*
- ** Apparently, this one uses different pictures than others that we
- ** have loaded. So, we build a new one.
- */
-
- mBailIfNULL_(outPICTOffscreen = malloc(sizeof(iPICTOffscreen)));
-
-
- iPICTOffscreen_ZeroOut(outPICTOffscreen);
-
- outPICTOffscreen->basePictureID = inBasePictureID;
- outPICTOffscreen->numFaces = inNumFaces;
-
-
- /*
- ** In order to determine how large of a GWorld to create to store
- ** all of our pictures, we need to grab the first one to get the rect
- **
- ** NOTE: We are assuming that ALL THE PICTURES ARE THE SAME SIZE!!!
- */
-
-
- mBailIfNULL_(currentPicture = GetPicture(outPICTOffscreen->basePictureID));
-
- /*
- ** Our GWorld rect is going to be very long and horizontal.
- ** each face of the sprite is stored in it so we make it
- ** as wide as our picture * the number of faces
- */
-
- outPICTOffscreen->sourceRect.top =
- outPICTOffscreen->sourceRect.left = 0;
- outPICTOffscreen->sourceRect.right = (**currentPicture).picFrame.right;
- outPICTOffscreen->sourceRect.bottom = (**currentPicture).picFrame.bottom;
-
- gworldRect.top =
- gworldRect.left = 0;
- gworldRect.right = ((**currentPicture).picFrame.right *
- outPICTOffscreen->numFaces);
- gworldRect.bottom = (**currentPicture).picFrame.bottom;
-
- /*
- ** We got what we needed, so let's get rid of it
- */
- ReleaseResource((Handle)currentPicture);
- currentPicture = NULL;
-
- /*
- ** Allocate it
- */
- if (NewGWorld(
- &outPICTOffscreen->sourcePort,
- 16,
- &gworldRect,
- NULL,
- NULL,
- useTempMem) == noErr)
-
- {
- PixMapHandle hPixMap;
- CGrafPtr savedPort;
- GDHandle savedGDevice;
-
- GetGWorld(&savedPort, &savedGDevice);
- SetGWorld(outPICTOffscreen->sourcePort, NULL);
-
- EraseRect(&outPICTOffscreen->sourcePort->portRect);
-
- SetGWorld(savedPort, savedGDevice);
-
- hPixMap = GetGWorldPixMap (outPICTOffscreen->sourcePort);
- HLock ((Handle) hPixMap);
- LockPixels (hPixMap);
-
- } else {
- status = kQ3Failure;
- goto bail;
- }
-
-
- /*
- ** Now, we fill it up with pictures
- */
-
-
- {
- long i = 0;
- GWorldPtr savedGWorld;
- GDHandle savedGDevice;
-
- GetGWorld(&savedGWorld, &savedGDevice);
- SetGWorld(outPICTOffscreen->sourcePort, NULL);
-
- /*
- ** INV: Port is changed
- */
-
- for (i = 0; i < outPICTOffscreen->numFaces; i++)
- {
- Rect picDestRect;
-
- if ((currentPicture =
- GetPicture(outPICTOffscreen->basePictureID + i)) == NULL)
- {
- SetGWorld(savedGWorld, savedGDevice);
- /*
- ** INV: Port is reset
- */
-
- goto bail;
- }
-
- picDestRect = (**currentPicture).picFrame;
- OffsetRect(&picDestRect, i * picDestRect.right, 0);
- DrawPicture(currentPicture, &picDestRect);
-
- ReleaseResource((Handle)currentPicture);
- currentPicture = NULL;
-
- } /* for all faces */
-
- SetGWorld(savedGWorld, savedGDevice);
- /*
- ** INV: Port is reset
- */
-
- }
-
- return outPICTOffscreen;
-
- bail:
-
- if (outPICTOffscreen)
- iPICTOffscreen_Dispose(outPICTOffscreen);
-
- if (currentPicture)
- ReleaseResource((Handle)currentPicture);
-
- return NULL;
- }
-
-
- /*===========================================================================*\
- *
- * Routine: iPICTOffscreen_Draw()
- *
- * Comments:
- *
- \*===========================================================================*/
-
- static TQ3Status iPICTOffscreen_Draw(
- iPICTOffscreen *inPICTOffscreen,
- long face,
- CGrafPtr destPort,
- const Rect *destRect
- )
- {
- TQ3Status status = kQ3Success;
-
- assert(inPICTOffscreen);
- assert(destPort);
-
- {
- /*
- ** Sorry this is so ugly.
- */
-
-
- Rect offsetRect = inPICTOffscreen->sourceRect;
-
- /*
- ** we have to save the last port
- */
- GWorldPtr savedPort;
- GDHandle tempGDHandle;
-
- /*
- ** These are used for *one* call, that being the one to CopyBits
- ** setting up the environment just so, will allow the fastest
- ** blitting
- */
-
- RGBColor savedForeground,
- savedBackground;
- RGBColor white = {0xFFFF, 0xFFFF, 0xFFFF};
- RGBColor black = {0, 0, 0};
- PixMapHandle offscreenBitmap = NULL;
- PixMapHandle destBitmap = NULL;
-
- OffsetRect(&offsetRect, offsetRect.right * face, 0);
-
- /*
- ** save off the port
- */
- GetGWorld((GWorldPtr*)&savedPort, &tempGDHandle);
-
- /*
- ** now, we get ready to CopyBits. There is some setup to make it
- ** fast, so we do that first.
- */
- GetForeColor (&savedForeground);
- GetBackColor (&savedBackground);
-
- RGBForeColor (&black);
- RGBBackColor (&white);
-
- /*
- ** Grab the source and destination pixmaps
- */
- destBitmap = GetGWorldPixMap (destPort);
- offscreenBitmap = GetGWorldPixMap (inPICTOffscreen->sourcePort);
-
- /*
- ** Now for God knows why, we have to set the GWorld to the
- ** *destination* of our CopyBits or prepare to Restart.
- */
- SetPort((GrafPort *)destPort);
-
-
- /*
- ** Again, for God knows why, we have to do a PenNormal here
- ** or CopyBits works weird.
- */
- PenNormal();
-
- /*
- ** do it.
- ** BTW, we use the fOffscreen->portRect twice because it's
- ** at 0,0 and that's what we want.
- */
-
- CopyBits ((const struct BitMap *)*offscreenBitmap,
- (const struct BitMap *)*destBitmap,
- &offsetRect,
- destRect,
- srcCopy | ditherCopy, 0L);
-
- /*
- ** Restore all that stuff
- */
- RGBForeColor (&savedForeground);
- RGBBackColor (&savedBackground);
-
- /*
- ** We can't forget to restore our original port
- */
- SetGWorld((CGrafPtr)savedPort, tempGDHandle);
-
- }
-
- return status;
- }
-
-
- /*===========================================================================*\
- *
- * Routine: iPICTOffscreen_Dispose()
- *
- * Comments:
- *
- \*===========================================================================*/
-
- static TQ3Status iPICTOffscreen_Dispose(
- iPICTOffscreen *ioPICTOffscreen)
- {
-
- assert(ioPICTOffscreen);
-
- if (ioPICTOffscreen->referenceCount > 1)
- {
- ioPICTOffscreen->referenceCount++;
-
- return kQ3Success;
- }
-
- else {
-
- if (ioPICTOffscreen->sourcePort)
- {
- PixMapHandle hPixMap;
-
- hPixMap = GetGWorldPixMap (ioPICTOffscreen->sourcePort);
-
- HUnlock ((Handle) hPixMap);
- UnlockPixels (hPixMap);
-
- DisposeGWorld (ioPICTOffscreen->sourcePort);
- }
-
- free(ioPICTOffscreen);
-
- }
-
- return kQ3Success;
- }
-
-
- /*===========================================================================*\
- *
- * Routine: iPICTOffscreen_Find()
- *
- * Comments:
- *
- \*===========================================================================*/
-
- static iPICTOffscreen *iPICTOffscreen_Find(
- long inBasePictureID)
- {
- iPICTOffscreen *iterator = gOffscreenHead;
- long done = false;
-
- while ((iterator != NULL) && !done)
- {
- if (inBasePictureID == iterator->basePictureID)
- done = true;
- else
- iterator = iterator->nextOffscreen;
- }
-
- return iterator;
-
- }
-
-
-